#ifndef SPL_SETTINGS
#define SPL_SETTINGS

class DLLEXPORT SettingsBase {
private:
    PTSTR szLocation;

public:
    SettingsBase(PCTSTR szLocation);
    virtual ~SettingsBase();

    virtual BOOL init() = 0;

    virtual BOOL getSetting(PCTSTR szName,
        PTSTR __out *value, DWORD __out *dwSize) = 0;
    virtual BOOL getSetting(PCTSTR szName, LONG __out *value) = 0;
    virtual BOOL getSetting(PCTSTR szName, INT __out *value) = 0;
    virtual BOOL getSetting(PCTSTR szName, DOUBLE __out *value) = 0;

    virtual BOOL setSetting(PCTSTR szName,
        PCTSTR __in value, DWORD __in dwSize) = 0;
    virtual BOOL setSetting(PCTSTR szName, LONG __in value) = 0;
    virtual BOOL setSetting(PCTSTR szName, INT __in value) = 0;
    virtual BOOL setSetting(PCTSTR szName, DOUBLE __in value) = 0;

    SPLINL BOOL setSetting(PCTSTR szName, PCTSTR __in value)
    {
        // save setting
        return setSetting(szName, value, (DWORD)_tcslen(value) + 1);
    }

    SPLINL PCTSTR getLocation() { return szLocation; }
};

class DLLEXPORT FileSettings : SettingsBase {
private:
    HANDLE hFile;
    TCHAR *pBuffer;
    DWORD dwBufferSize;
    ULONGLONG lWriteTime;

    void readSettings();

public:
    FileSettings(PCTSTR szLocation);
    ~FileSettings();

    BOOL init();
    BOOL getOffset(PCTSTR szName, PTCHAR __out *pStart, PTCHAR __out *pEnd);

    BOOL getSetting(PCTSTR szName, PTSTR __out *value, DWORD __out *dwSize);
    BOOL getSetting(PCTSTR szName, BYTE __out *bHotkeyMod, BYTE __out *bHotkeyVK);
    BOOL getSetting(PCTSTR szName, Geom::Size __out &value);
    BOOL getSetting(PCTSTR szName, Geom::Bounds __out &value);
    BOOL getSetting(PCTSTR szName, LONG __out *value);
    BOOL getSetting(PCTSTR szName, INT __out *value);
    BOOL getSetting(PCTSTR szName, DOUBLE __out *value);

    BOOL setSetting(PCTSTR szName, PCTSTR __in value, DWORD __in dwSize);
    BOOL setSetting(PCTSTR szName, BYTE bHotkeyMod, BYTE bHotkeyVK);
    BOOL setSetting(PCTSTR szName, Geom::Size __in value);
    BOOL setSetting(PCTSTR szName, Geom::Bounds __in value);
    BOOL setSetting(PCTSTR szName, LONG __in value);
    BOOL setSetting(PCTSTR szName, INT __in value);
    BOOL setSetting(PCTSTR szName, DOUBLE __in value);
};

class DLLEXPORT RegistrySettings : SettingsBase {
private:
    HKEY hKey;

public:
    RegistrySettings(PCTSTR szLocation);
    ~RegistrySettings();

    BOOL init();

    BOOL getSetting(PCTSTR szName, PTSTR __out *value, DWORD __out *dwSize);
    BOOL getSetting(PCTSTR szName, LONG __out *value);
    BOOL getSetting(PCTSTR szName, INT __out *value);
    BOOL getSetting(PCTSTR szName, DOUBLE __out *value);

    BOOL setSetting(PCTSTR szName, PCTSTR __in value, DWORD __in dwSize);
    BOOL setSetting(PCTSTR szName, LONG __in value);
    BOOL setSetting(PCTSTR szName, INT __in value);
    BOOL setSetting(PCTSTR szName, DOUBLE __in value);
};

#endif